home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / less_14z / part04 < prev    next >
Internet Message Format  |  1991-07-08  |  51KB

  1. Path: news.larc.nasa.gov!amiga-request
  2. From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
  3. Subject: v91i130: Less 1.4Z - text pager, Part04/07
  4. Reply-To: rayz@altair.csustan.edu (R. L. Zarling)
  5. Newsgroups: comp.sources.amiga
  6. Message-ID: <comp.sources.amiga.v91i130@ab20.larc.nasa.gov>
  7. References: <comp.sources.amiga.v91i127@ab20.larc.nasa.gov>
  8. Date: 04 Jul 91 17:28:18 GMT
  9. Approved: tadguy@uunet.UU.NET (Tad Guy)
  10. X-Mail-Submissions-To: amiga@uunet.uu.net
  11. X-Post-Discussions-To: comp.sys.amiga.misc
  12.  
  13. Submitted-by: rayz@altair.csustan.edu (R. L. Zarling)
  14. Posting-number: Volume 91, Issue 130
  15. Archive-name: utilities/less-1.4z/part04
  16.  
  17. #!/bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 4 (of 7)."
  24. # Contents:  Less1.4Z/src/line.c Less1.4Z/src/prim.c
  25. # Wrapped by tadguy@ab20 on Thu Jul  4 13:28:15 1991
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'Less1.4Z/src/line.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'Less1.4Z/src/line.c'\"
  29. else
  30. echo shar: Extracting \"'Less1.4Z/src/line.c'\" \(24485 characters\)
  31. sed "s/^X//" >'Less1.4Z/src/line.c' <<'END_OF_FILE'
  32. X/*
  33. X * Routines to manipulate the "line buffer".
  34. X * The line buffer holds a line of output as it is being built
  35. X * in preparation for output to the screen.
  36. X * We keep track of the PRINTABLE length of the line as it is being built.
  37. X */
  38. X
  39. X#ifdef AMIGA
  40. X/* Compile with -HPreHeader.q to get "less.h"! */
  41. X#else
  42. X#include "less.h"
  43. X#endif
  44. X
  45. X
  46. Xstatic char linebuf[1024];      /* Buffer which holds the current output line */
  47. Xstatic char *curr;              /* Pointer into linebuf */
  48. Xstatic int column;              /* Printable length, accounting for
  49. X                                   backspaces, etc. */
  50. X/*
  51. X * A ridiculously complex state machine takes care of backspaces
  52. X * when in BS_SPECIAL mode.  The complexity arises from the attempt
  53. X * to deal with all cases, especially involving long lines with underlining,
  54. X * boldfacing or whatever.  There are still some cases which will break it.
  55. X *
  56. X * If ANSIGR is defined, we also recognized ANSI Graphic Rendition commands
  57. X * for underline, boldface, italics, and inverse video.  As with the
  58. X * backspace modes, the emulation is imperfect and can be broken under
  59. X * certain rare circumstances.
  60. X *
  61. X * There are five (four, if not ANSIGR) states:
  62. X *      LN_NORMAL is the normal state (not in underline mode).
  63. X *      LN_UNDERLINE means we are in underline mode.  We expect to get
  64. X *              either a sequence like "_\bX" or "X\b_" to continue
  65. X *              underline mode, or anything else to end underline mode.
  66. X *      LN_BOLDFACE means we are in boldface mode.  We expect to get sequences
  67. X *              like "X\bX\b...X\bX" to continue boldface mode, or anything
  68. X *              else to end boldface mode.
  69. X *      LN_UL_X means we are one character after LN_UNDERLINE
  70. X *              (we have gotten the '_' in "_\bX" or the 'X' in "X\b_").
  71. X *      LN_UL_XB means we are one character after LN_UL_X
  72. X *              (we have gotten the backspace in "_\bX" or "X\b_";
  73. X *              we expect one more ordinary character,
  74. X *              which will put us back in state LN_UNDERLINE).
  75. X *      LN_BO_X means we are one character after LN_BOLDFACE
  76. X *              (we have gotten the 'X' in "X\bX").
  77. X *      LN_BO_XB means we are one character after LN_BO_X
  78. X *              (we have gotten the backspace in "X\bX";
  79. X *              we expect one more 'X' which will put us back
  80. X *              in LN_BOLDFACE).
  81. X *ifdef ANSIGR
  82. X *      LN_CSI  means we are in an ANSI Graphic Rendition sequence.
  83. X *              Variable AnsiLen is the number of characters we have seen
  84. X *              before this one in this sequence.  AnsiMode is the numeric
  85. X *              value of the first character after the CSI.
  86. X *endif
  87. X */
  88. Xstatic int ln_state;            /* Currently in normal/underline/bold/etc mode? */
  89. X#define LN_NORMAL       0       /* Not in underline, boldface or whatever mode */
  90. X#define LN_UNDERLINE    1       /* In underline, need next char */
  91. X#define LN_UL_X         2       /* In underline, got char, need \b */
  92. X#define LN_UL_XB        3       /* In underline, got char & \b, need one more */
  93. X#define LN_BOLDFACE     4       /* In boldface, need next char */
  94. X#define LN_BO_X         5       /* In boldface, got char, need \b */
  95. X#define LN_BO_XB        6       /* In boldface, got char & \b, need same char */
  96. X#ifdef ANSIGR
  97. X#define LN_CSI          7       /* In an Ansi Graphic Rendition sequence */
  98. X
  99. Xstatic int AnsiLen, AnsiMode, AnsiNum;
  100. X#endif
  101. X
  102. Xpublic char *line;              /* Pointer to the current line.
  103. X                                   Usually points to linebuf. */
  104. X
  105. Xextern int bs_mode;
  106. Xextern int tabstop;
  107. Xextern int bo_width, be_width;
  108. Xextern int ul_width, ue_width;
  109. X#ifdef AMIGA
  110. Xextern int it_width, ie_width;
  111. Xextern int nv_width, ne_width;
  112. X#endif
  113. Xextern int sc_width, sc_height;
  114. X
  115. X/*
  116. X * Rewind the line buffer.
  117. X */
  118. X#ifdef __STDC__
  119. Xvoid prewind (void)
  120. X#else
  121. X        public void
  122. Xprewind()
  123. X#endif
  124. X{
  125. X        line = curr = linebuf;
  126. X        ln_state = LN_NORMAL;
  127. X        column = 0;
  128. X}
  129. X
  130. X/*
  131. X * Append a character to the line buffer.
  132. X * Expand tabs into spaces, handle underlining, boldfacing, etc.
  133. X * Returns 0 if ok, 1 if couldn't fit in buffer.
  134. X */
  135. X
  136. X#ifdef AMIGA
  137. X/* ue_width is zero on the Amiga */
  138. X#define NEW_COLUMN(newcol)      if ((newcol) > sc_width) \
  139. X                                        return (1); else column = (newcol)
  140. X
  141. X#else
  142. X#define NEW_COLUMN(newcol)      if ((newcol) + ((ln_state)?ue_width:0) > sc_width) \
  143. X                                        return (1); else column = (newcol)
  144. X#endif
  145. X
  146. X#ifdef __STDC__
  147. Xint pappend (int c)
  148. X#else
  149. X        public int
  150. Xpappend(c)
  151. X        int c;
  152. X#endif
  153. X{
  154. X        if (c == '\0')
  155. X        {
  156. X                /*
  157. X                 * Terminate any special modes, if necessary.
  158. X                 * Append a '\0' to the end of the line.
  159. X                 */
  160. X                switch (ln_state)
  161. X                {
  162. X                case LN_UL_X:
  163. X                        curr[0] = curr[-1];
  164. X                        curr[-1] = UE_CHAR;
  165. X                        curr++;
  166. X                        break;
  167. X                case LN_BO_X:
  168. X                        curr[0] = curr[-1];
  169. X                        curr[-1] = BE_CHAR;
  170. X                        curr++;
  171. X                        break;
  172. X                case LN_UL_XB:
  173. X                case LN_UNDERLINE:
  174. X                        *curr++ = UE_CHAR;
  175. X                        break;
  176. X                case LN_BO_XB:
  177. X                case LN_BOLDFACE:
  178. X                        *curr++ = BE_CHAR;
  179. X                        break;
  180. X                }
  181. X                ln_state = LN_NORMAL;
  182. X                *curr = '\0';
  183. X                return (0);
  184. X        }
  185. X
  186. X        if (curr > linebuf + sizeof(linebuf) - 12)
  187. X                /*
  188. X                 * Almost out of room in the line buffer.
  189. X                 * Don't take any chances.
  190. X                 * {{ Linebuf is supposed to be big enough that this
  191. X                 *    will never happen, but may need to be made
  192. X                 *    bigger for wide screens or lots of backspaces. }}
  193. X                 */
  194. X                return (1);
  195. X
  196. X        if (bs_mode == BS_SPECIAL)
  197. X        {
  198. X                /*
  199. X                 * Advance the state machine.
  200. X                 */
  201. X                switch (ln_state)
  202. X                {
  203. X#ifdef ANSIGR
  204. X                case LN_CSI:
  205. X                /* interpret an ANSI control string.  We have seen an ESC
  206. X                   or CSI (0x9b) and possibly some more characters that
  207. X                   make a valid prefix of an ANSI set-graphics-mode cmd.
  208. X                   As long as the prefix remains valid, nothing is put in
  209. X                   the line buffer.  This avoids the buffer overflowing
  210. X                   before we reach the end of some long ANSI sequence.
  211. X                   If we get an invalid character in the sequence, we
  212. X                   start printing control characters with the first thing
  213. X                   we did not recognize.
  214. X                */
  215. X                        if ( c == '[' && AnsiLen == 1 ) /* esc-[ ? */
  216. X                            return 0;
  217. X                        if ( c == ';' || c == 'm' )
  218. X                            if ( AnsiNum >= 0 && AnsiNum < 8 )
  219. X                                AnsiMode = AnsiNum;
  220. X                        if ( !isdigit(c) )
  221. X                            AnsiNum = -1;
  222. X                        if ( c == 'm' ) /* end of sequence ? */
  223. X                        {
  224. X                            ln_state = LN_NORMAL;
  225. X                            switch ( AnsiMode )
  226. X                            {
  227. X                            /* Note: several NEW_COLUMN lines are commented
  228. X                            out in the following code.  Even though this is
  229. X                            Amiga-specific code, the 'column' *should* be
  230. X                            reset in each of these cases.  It just so
  231. X                            happens that all the xx_width are zero, so the
  232. X                            whole thing is academic.
  233. X                            */
  234. X                            case -1: /* no mode set */
  235. X                                    return 0;
  236. X                            case 0:  /* normal */
  237. X                                    *curr++ = UE_CHAR;
  238. X                                    /* NEW_COLUMN(column+ue_width); */
  239. X                                    return 0;
  240. X                            case 1:  /* bold */
  241. X                                    *curr++ = BO_CHAR;
  242. X                                    /* NEW_COLUMN(column+bo_width); */
  243. X                                    return 0;
  244. X                            case 3:  /* Italic */
  245. X                                    *curr++ = IT_CHAR;
  246. X                                    /* NEW_COLUMN(column+it_width); */
  247. X                                    return 0;
  248. X                            case 4:  /* underline */
  249. X                                    *curr++ = UL_CHAR;
  250. X                                    /* NEW_COLUMN(column+ul_width); */
  251. X                                    return 0;
  252. X                            case 7:  /* inverse video */
  253. X                                    *curr++ = NV_CHAR;
  254. X                                    /* NEW_COLUMN(column+nv_width); */
  255. X                                    return 0;
  256. X                            default: return 0;
  257. X                            }
  258. X                        }
  259. X                        else if ( isdigit(c) )
  260. X                        {
  261. X                            AnsiLen++;
  262. X                            if (AnsiNum < 0) AnsiNum = 0;
  263. X                            AnsiNum *= 10;
  264. X                            AnsiNum += c - '0';
  265. X                            return 0;
  266. X                        }
  267. X                        else if ( c == ';' )
  268. X                        {
  269. X                            AnsiLen++;
  270. X                            return 0;
  271. X                        }
  272. X                        else ln_state = LN_NORMAL;
  273. X                        /* v v v fall through v v v */
  274. X#endif
  275. X                case LN_NORMAL:
  276. X#ifdef ANSIGR
  277. X                        if ( (unsigned char)c == 0x9b || c == 0x1b )
  278. X                        {
  279. X                                ln_state = LN_CSI;
  280. X                                AnsiMode = -1;
  281. X                                AnsiLen = 1;
  282. X                                AnsiNum = -1;
  283. X                                return 0;
  284. X                        }
  285. X#endif
  286. X                        if (curr <= linebuf + 1 || curr[-1] != '\b')
  287. X                                break;
  288. X
  289. X                        if (c == curr[-2])
  290. X                                goto enter_boldface;
  291. X                        if (c == '_' || curr[-2] == '_')
  292. X                                goto enter_underline;
  293. X                        curr -= 2;
  294. X                        break;
  295. X
  296. Xenter_boldface:
  297. X                        /*
  298. X                         * We have "X\bX" (including the current char).
  299. X                         * Switch into boldface mode.
  300. X                         */
  301. X                        if (column + bo_width + be_width + 1 >= sc_width)
  302. X                                /*
  303. X                                 * Not enough room left on the screen to
  304. X                                 * enter and exit boldface mode.
  305. X                                 */
  306. X                                return (1);
  307. X
  308. X                        if (bo_width > 0 &&
  309. X                            curr > linebuf + 2 && curr[-3] == ' ')
  310. X                        {
  311. X                                /*
  312. X                                 * Special case for magic cookie terminals:
  313. X                                 * if the previous char was a space, replace
  314. X                                 * it with the "enter boldface" sequence.
  315. X                                 */
  316. X                                curr[-3] = BO_CHAR;
  317. X                                column += bo_width-1;
  318. X                        } else
  319. X                        {
  320. X                                curr[-1] = curr[-2];
  321. X                                curr[-2] = BO_CHAR;
  322. X                                column += bo_width;
  323. X                                curr++;
  324. X                        }
  325. X                        goto ln_bo_xb_case;
  326. X
  327. Xenter_underline:
  328. X                        /*
  329. X                         * We have either "_\bX" or "X\b_" (including
  330. X                         * the current char).  Switch into underline mode.
  331. X                         */
  332. X                        if (column + ul_width + ue_width + 1 >= sc_width)
  333. X                                /*
  334. X                                 * Not enough room left on the screen to
  335. X                                 * enter and exit underline mode.
  336. X                                 */
  337. X                                return (1);
  338. X
  339. X                        if (ul_width > 0 &&
  340. X                            curr > linebuf + 2 && curr[-3] == ' ')
  341. X                        {
  342. X                                /*
  343. X                                 * Special case for magic cookie terminals:
  344. X                                 * if the previous char was a space, replace
  345. X                                 * it with the "enter underline" sequence.
  346. X                                 */
  347. X                                curr[-3] = UL_CHAR;
  348. X                                column += ul_width-1;
  349. X                        } else
  350. X                        {
  351. X                                curr[-1] = curr[-2];
  352. X                                curr[-2] = UL_CHAR;
  353. X                                column += ul_width;
  354. X                                curr++;
  355. X                        }
  356. X                        goto ln_ul_xb_case;
  357. X                        /*NOTREACHED*/
  358. X                case LN_UL_XB:
  359. X                        /*
  360. X                         * Termination of a sequence "_\bX" or "X\b_".
  361. X                         */
  362. X                        if (c != '_' && curr[-2] != '_' && c == curr[-2])
  363. X                        {
  364. X                                /*
  365. X                                 * We seem to have run on from underlining
  366. X                                 * into boldfacing - this is a nasty fix, but
  367. X                                 * until this whole routine is rewritten as a
  368. X                                 * real DFA, ...  well ...
  369. X                                 */
  370. X                                curr[0] = curr[-2];
  371. X                                curr[-2] = UE_CHAR;
  372. X                                curr[-1] = BO_CHAR;
  373. X                                curr += 2; /* char & non-existent backspace */
  374. X                                ln_state = LN_BO_XB;
  375. X                                goto ln_bo_xb_case;
  376. X                        }
  377. Xln_ul_xb_case:
  378. X                        if (c == '_')
  379. X                                c = curr[-2];
  380. X                        curr -= 2;
  381. X                        ln_state = LN_UNDERLINE;
  382. X                        break;
  383. X                case LN_BO_XB:
  384. X                        /*
  385. X                         * Termination of a sequnce "X\bX".
  386. X                         */
  387. X                        if (c != curr[-2] && (c == '_' || curr[-2] == '_'))
  388. X                        {
  389. X                                /*
  390. X                                 * We seem to have run on from
  391. X                                 * boldfacing into underlining.
  392. X                                 */
  393. X                                curr[0] = curr[-2];
  394. X                                curr[-2] = BE_CHAR;
  395. X                                curr[-1] = UL_CHAR;
  396. X                                curr += 2; /* char & non-existent backspace */
  397. X                                ln_state = LN_UL_XB;
  398. X                                goto ln_ul_xb_case;
  399. X                        }
  400. Xln_bo_xb_case:
  401. X                        curr -= 2;
  402. X                        ln_state = LN_BOLDFACE;
  403. X                        break;
  404. X                case LN_UNDERLINE:
  405. X                        if (column + ue_width + bo_width + 1 + be_width >= sc_width)
  406. X                                /*
  407. X                                 * We have just barely enough room to
  408. X                                 * exit underline mode and handle a possible
  409. X                                 * underline/boldface run on mixup.
  410. X                                 */
  411. X                                return (1);
  412. X                        ln_state = LN_UL_X;
  413. X                        break;
  414. X                case LN_BOLDFACE:
  415. X                        if (c == '\b')
  416. X                        {
  417. X                                ln_state = LN_BO_XB;
  418. X                                break;
  419. X                        }
  420. X                        if (column + be_width + ul_width + 1 + ue_width >= sc_width)
  421. X                                /*
  422. X                                 * We have just barely enough room to
  423. X                                 * exit underline mode and handle a possible
  424. X                                 * underline/boldface run on mixup.
  425. X                                 */
  426. X                                return (1);
  427. X                        ln_state = LN_BO_X;
  428. X                        break;
  429. X                case LN_UL_X:
  430. X                        if (c == '\b')
  431. X                                ln_state = LN_UL_XB;
  432. X                        else
  433. X                        {
  434. X                                /*
  435. X                                 * Exit underline mode.
  436. X                                 * We have to shuffle the chars a bit
  437. X                                 * to make this work.
  438. X                                 */
  439. X                                curr[0] = curr[-1];
  440. X                                curr[-1] = UE_CHAR;
  441. X                                column += ue_width;
  442. X                                if (ue_width > 0 && curr[0] == ' ')
  443. X                                        /*
  444. X                                         * Another special case for magic
  445. X                                         * cookie terminals: if the next
  446. X                                         * char is a space, replace it
  447. X                                         * with the "exit underline" sequence.
  448. X                                         */
  449. X                                        column--;
  450. X                                else
  451. X                                        curr++;
  452. X                                ln_state = LN_NORMAL;
  453. X                        }
  454. X                        break;
  455. X                case LN_BO_X:
  456. X                        if (c == '\b')
  457. X                                ln_state = LN_BO_XB;
  458. X                        else
  459. X                        {
  460. X                                /*
  461. X                                 * Exit boldface mode.
  462. X                                 * We have to shuffle the chars a bit
  463. X                                 * to make this work.
  464. X                                 */
  465. X                                curr[0] = curr[-1];
  466. X                                curr[-1] = BE_CHAR;
  467. X                                column += be_width;
  468. X                                if (be_width > 0 && curr[0] == ' ')
  469. X                                        /*
  470. X                                         * Another special case for magic
  471. X                                         * cookie terminals: if the next
  472. X                                         * char is a space, replace it
  473. X                                         * with the "exit boldface" sequence.
  474. X                                         */
  475. X                                        column--;
  476. X                                else
  477. X                                        curr++;
  478. X                                ln_state = LN_NORMAL;
  479. X                        }
  480. X                        break;
  481. X                }
  482. X        }
  483. X
  484. X        if (c == '\t')
  485. X        {
  486. X                /*
  487. X                 * Expand a tab into spaces.
  488. X                 */
  489. X                do
  490. X                {
  491. X                        NEW_COLUMN(column+1);
  492. X                } while ((column % tabstop) != 0);
  493. X                *curr++ = '\t';
  494. X                return (0);
  495. X        }
  496. X
  497. X        if (c == '\b')
  498. X        {
  499. X                if (bs_mode == BS_CONTROL)
  500. X                {
  501. X                        /*
  502. X                         * Treat backspace as a control char: output "^H".
  503. X                         */
  504. X                        NEW_COLUMN(column+2);
  505. X#ifdef EIGHTBIT
  506. X                        *curr++ = c;
  507. X#else
  508. X                        *curr++ = ('H' | 0200);
  509. X#endif
  510. X                } else
  511. X                {
  512. X                        /*
  513. X                         * Output a real backspace.
  514. X                         */
  515. X                        column--;
  516. X                        *curr++ = '\b';
  517. X                }
  518. X                return (0);
  519. X        }
  520. X
  521. X        if (control_char(c))
  522. X        {
  523. X                /*
  524. X                 * Put a "^X" into the buffer.
  525. X                 * The 0200 bit is used to tell put_line() to prefix
  526. X                 * the char with a ^.  We don't actually put the ^
  527. X                 * in the buffer because we sometimes need to move
  528. X                 * chars around, and such movement might separate
  529. X                 * the ^ from its following character.
  530. X                 * {{ This should be redone so that we can use an
  531. X                 *    8 bit (e.g. international) character set. }}
  532. X                 */
  533. X                NEW_COLUMN(column+2);
  534. X                *curr++ =
  535. X#ifdef EIGHTBIT
  536. X                    c;
  537. X#else
  538. X                    (carat_char(c) | 0200);
  539. X#endif
  540. X                return (0);
  541. X        }
  542. X
  543. X        /*
  544. X         * Ordinary character.  Just put it in the buffer.
  545. X         */
  546. X        NEW_COLUMN(column+1);
  547. X        *curr++ = c;
  548. X        return (0);
  549. X}
  550. X
  551. X/*
  552. X * Analogous to forw_line(), but deals with "raw lines":
  553. X * lines which are not split for screen width.
  554. X * {{ This is supposed to be more efficient than forw_line(). }}
  555. X */
  556. X#ifdef __STDC__
  557. XPOSITION forw_raw_line (POSITION curr_pos)
  558. X#else
  559. X        public POSITION
  560. Xforw_raw_line(curr_pos)
  561. X        POSITION curr_pos;
  562. X#endif
  563. X{
  564. X        register char *p;
  565. X        register int c;
  566. X        POSITION new_pos;
  567. X
  568. X        if (curr_pos == NULL_POSITION || ch_seek(curr_pos) ||
  569. X                (c = ch_forw_get()) == EOF)
  570. X                return (NULL_POSITION);
  571. X
  572. X        p = linebuf;
  573. X
  574. X        for (;;)
  575. X        {
  576. X                if (c == '\n' || c == EOF)
  577. X                {
  578. X                        new_pos = ch_tell();
  579. X                        break;
  580. X                }
  581. X                if (p >= &linebuf[sizeof(linebuf)-1])
  582. X                {
  583. X                        /*
  584. X                         * Overflowed the input buffer.
  585. X                         * Pretend the line ended here.
  586. X                         * {{ The line buffer is supposed to be big
  587. X                         *    enough that this never happens. }}
  588. X                         */
  589. X                        new_pos = ch_tell() - 1;
  590. X                        break;
  591. X                }
  592. X                *p++ = c;
  593. X                c = ch_forw_get();
  594. X        }
  595. X        *p = '\0';
  596. X        line = linebuf;
  597. X        return (new_pos);
  598. X}
  599. X
  600. X/*
  601. X * Analogous to back_line(), but deals with "raw lines".
  602. X * {{ This is supposed to be more efficient than back_line(). }}
  603. X */
  604. X#ifdef __STDC__
  605. XPOSITION back_raw_line (POSITION curr_pos)
  606. X#else
  607. X        public POSITION
  608. Xback_raw_line(curr_pos)
  609. X        POSITION curr_pos;
  610. X#endif
  611. X{
  612. X        register char *p;
  613. X        register int c;
  614. X        POSITION new_pos;
  615. X
  616. X        if (curr_pos == NULL_POSITION || curr_pos <= (POSITION)0 ||
  617. X                ch_seek(curr_pos-1))
  618. X                return (NULL_POSITION);
  619. X
  620. X        p = &linebuf[sizeof(linebuf)];
  621. X        *--p = '\0';
  622. X
  623. X        for (;;)
  624. X        {
  625. X                c = ch_back_get();
  626. X                if (c == '\n')
  627. X                {
  628. X                        /*
  629. X                         * This is the newline ending the previous line.
  630. X                         * We have hit the beginning of the line.
  631. X                         */
  632. X                        new_pos = ch_tell() + 1;
  633. X                        break;
  634. X                }
  635. X                if (c == EOF)
  636. X                {
  637. X                        /*
  638. X                         * We have hit the beginning of the file.
  639. X                         * This must be the first line in the file.
  640. X                         * This must, of course, be the beginning of the line.
  641. X                         */
  642. X                        new_pos = (POSITION)0;
  643. X                        break;
  644. X                }
  645. X                if (p <= linebuf)
  646. X                {
  647. X                        /*
  648. X                         * Overflowed the input buffer.
  649. X                         * Pretend the line ended here.
  650. X                         */
  651. X                        new_pos = ch_tell() + 1;
  652. X                        break;
  653. X                }
  654. X                *--p = c;
  655. X        }
  656. X        line = p;
  657. X        return (new_pos);
  658. X}
  659. END_OF_FILE
  660. if test 24485 -ne `wc -c <'Less1.4Z/src/line.c'`; then
  661.     echo shar: \"'Less1.4Z/src/line.c'\" unpacked with wrong size!
  662. fi
  663. # end of 'Less1.4Z/src/line.c'
  664. fi
  665. if test -f 'Less1.4Z/src/prim.c' -a "${1}" != "-c" ; then 
  666.   echo shar: Will not clobber existing file \"'Less1.4Z/src/prim.c'\"
  667. else
  668. echo shar: Extracting \"'Less1.4Z/src/prim.c'\" \(22479 characters\)
  669. sed "s/^X//" >'Less1.4Z/src/prim.c' <<'END_OF_FILE'
  670. X/*
  671. X * Primitives for displaying the file on the screen.
  672. X */
  673. X
  674. X#ifdef AMIGA
  675. X#define REGCMP 1
  676. X#define regex regexec
  677. X#define regcmp(x,y) regcomp(x)
  678. X#include "regexp.h"
  679. X#endif
  680. X
  681. X#ifdef AMIGA
  682. X/* Compile with -HPreHeader.q to get "less.h"! */
  683. X#else
  684. X#include "less.h"
  685. X#endif
  686. X
  687. X#include "position.h"
  688. X
  689. X
  690. Xpublic int hit_eof;     /* Keeps track of how many times we hit end of file */
  691. X
  692. Xextern int quiet;
  693. Xextern int top_search;
  694. Xextern int top_scroll;
  695. Xextern int back_scroll;
  696. Xextern int sc_width, sc_height;
  697. Xextern int sigs;
  698. Xextern int quit_at_eof;
  699. Xextern int ac;
  700. Xextern char *line;
  701. Xextern char *first_cmd;
  702. X
  703. X/* Prototypes for functions defined in prim.c */
  704. X
  705. Xstatic void eof_bell __PROTO((void));
  706. Xstatic void eof_check __PROTO((void));
  707. Xstatic void forw __PROTO((register int n,
  708. X                          POSITION pos,
  709. X                          int force,
  710. X                          int only_last));
  711. Xstatic void back __PROTO((register int n,
  712. X                          POSITION pos,
  713. X                          int force,
  714. X                          int only_last));
  715. Xstatic void prepaint __PROTO((POSITION pos));
  716. Xstatic int badmark __PROTO((int c));
  717. Xstatic int match __PROTO((char *pattern,
  718. X                          char *buf));
  719. X
  720. X
  721. X
  722. X/*
  723. X * Sound the bell to indicate he is trying to move past end of file.
  724. X */
  725. X#ifdef __STDC__
  726. Xstatic void eof_bell (void)
  727. X#else
  728. X        static void
  729. Xeof_bell()
  730. X#endif
  731. X{
  732. X        if (quiet == NOT_QUIET)
  733. X                bell();
  734. X        else
  735. X                vbell();
  736. X}
  737. X
  738. X/*
  739. X * Check to see if the end of file is currently "displayed".
  740. X */
  741. X#ifdef __STDC__
  742. Xstatic void eof_check (void)
  743. X#else
  744. X        static void
  745. Xeof_check()
  746. X#endif
  747. X{
  748. X        POSITION pos;
  749. X
  750. X        /*
  751. X         * If the bottom line is empty, we are at EOF.
  752. X         * If the bottom line ends at the file length,
  753. X         * we must be just at EOF.
  754. X         */
  755. X        pos = position(BOTTOM_PLUS_ONE);
  756. X        if (pos == NULL_POSITION || pos == ch_length())
  757. X                hit_eof++;
  758. X}
  759. X
  760. X/*
  761. X * Display n lines, scrolling forward,
  762. X * starting at position pos in the input file.
  763. X * "force" means display the n lines even if we hit end of file.
  764. X * "only_last" means display only the last screenful if n > screen size.
  765. X */
  766. X#ifdef __STDC__
  767. Xstatic void forw (register int n, POSITION pos, int force, int only_last)
  768. X#else
  769. X        static void
  770. Xforw(n, pos, force, only_last)
  771. X        register int n;
  772. X        POSITION pos;
  773. X        int force;
  774. X        int only_last;
  775. X#endif
  776. X{
  777. X        int eof = 0;
  778. X        int nlines = 0;
  779. X        int do_repaint;
  780. X        static int first_time = 1;
  781. X
  782. X        /*
  783. X         * do_repaint tells us not to display anything till the end,
  784. X         * then just repaint the entire screen.
  785. X         */
  786. X        do_repaint = (only_last && n > sc_height-1);
  787. X
  788. X        if (!do_repaint)
  789. X        {
  790. X                if (top_scroll && n >= sc_height - 1)
  791. X                {
  792. X                        /*
  793. X                         * Start a new screen.
  794. X                         * {{ This is not really desirable if we happen
  795. X                         *    to hit eof in the middle of this screen,
  796. X                         *    but we don't yet know if that will happen. }}
  797. X                         */
  798. X                        if (top_scroll == 2)
  799. X                                clear();
  800. X                        home();
  801. X                        force = 1;
  802. X                } else
  803. X                {
  804. X                        lower_left();
  805. X                        clear_eol();
  806. X                }
  807. X
  808. X                if (pos != position(BOTTOM_PLUS_ONE))
  809. X                {
  810. X                        /*
  811. X                         * This is not contiguous with what is
  812. X                         * currently displayed.  Clear the screen image
  813. X                         * (position table) and start a new screen.
  814. X                         */
  815. X                        pos_clear();
  816. X                        add_forw_pos(pos);
  817. X                        force = 1;
  818. X                        if (top_scroll)
  819. X                        {
  820. X                                if (top_scroll == 2)
  821. X                                        clear();
  822. X                                home();
  823. X                        } else if (!first_time)
  824. X                        {
  825. X                                putstr("...skipping...\n");
  826. X                        }
  827. X                }
  828. X        }
  829. X
  830. X        while (--n >= 0)
  831. X        {
  832. X                /*
  833. X                 * Read the next line of input.
  834. X                 */
  835. X                pos = forw_line(pos);
  836. X                if (pos == NULL_POSITION)
  837. X                {
  838. X                        /*
  839. X                         * End of file: stop here unless the top line
  840. X                         * is still empty, or "force" is true.
  841. X                         */
  842. X                        eof = 1;
  843. X                        if (!force && position(TOP) != NULL_POSITION)
  844. X                                break;
  845. X                        line = NULL;
  846. X                }
  847. X                /*
  848. X                 * Add the position of the next line to the position table.
  849. X                 * Display the current line on the screen.
  850. X                 */
  851. X                add_forw_pos(pos);
  852. X                nlines++;
  853. X                if (do_repaint ||
  854. X                        (first_time && line == NULL && !top_scroll))
  855. X                        continue;
  856. X                if (top_scroll == 1)
  857. X                        clear_eol();
  858. X                put_line();
  859. X        }
  860. X
  861. X        if (eof)
  862. X                hit_eof++;
  863. X        else
  864. X                eof_check();
  865. X        if (nlines == 0)
  866. X                eof_bell();
  867. X        else if (do_repaint)
  868. X                repaint();
  869. X#ifndef AMIGA
  870. X        if (first_time && hit_eof && quit_at_eof && ac <= 1)
  871. X                quit();
  872. X#endif
  873. X        first_time = 0;
  874. X}
  875. X
  876. X/*
  877. X * Display n lines, scrolling backward.
  878. X */
  879. X#ifdef __STDC__
  880. Xstatic void back (register int n, POSITION pos, int force, int only_last)
  881. X#else
  882. X        static void
  883. Xback(n, pos, force, only_last)
  884. X        register int n;
  885. X        POSITION pos;
  886. X        int force;
  887. X        int only_last;
  888. X#endif
  889. X{
  890. X        int nlines = 0;
  891. X        int do_repaint;
  892. X
  893. X        do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1));
  894. X        hit_eof = 0;
  895. X        while (--n >= 0)
  896. X        {
  897. X                /*
  898. X                 * Get the previous line of input.
  899. X                 */
  900. X                pos = back_line(pos);
  901. X                if (pos == NULL_POSITION)
  902. X                {
  903. X                        /*
  904. X                         * Beginning of file: stop here unless "force" is true.
  905. X                         */
  906. X                        if (!force)
  907. X                                break;
  908. X                        line = NULL;
  909. X                }
  910. X                /*
  911. X                 * Add the position of the previous line to the position table.
  912. X                 * Display the line on the screen.
  913. X                 */
  914. X                add_back_pos(pos);
  915. X                nlines++;
  916. X                if (!do_repaint)
  917. X                {
  918. X                        home();
  919. X                        add_line();
  920. X                        put_line();
  921. X                }
  922. X        }
  923. X
  924. X        eof_check();
  925. X        if (nlines == 0)
  926. X                eof_bell();
  927. X        else if (do_repaint)
  928. X                repaint();
  929. X}
  930. X
  931. X/*
  932. X * Display n more lines, forward.
  933. X * Start just after the line currently displayed at the bottom of the screen.
  934. X */
  935. X#ifdef __STDC__
  936. Xvoid forward (int n, int only_last)
  937. X#else
  938. X        public void
  939. Xforward(n, only_last)
  940. X        int n;
  941. X        int only_last;
  942. X#endif
  943. X{
  944. X        POSITION pos;
  945. X
  946. X        pos = position(BOTTOM_PLUS_ONE);
  947. X        if (pos == NULL_POSITION)
  948. X        {
  949. X                eof_bell();
  950. X                hit_eof++;
  951. X                return;
  952. X        }
  953. X        forw(n, pos, 0, only_last);
  954. X}
  955. X
  956. X/*
  957. X * Display n more lines, backward.
  958. X * Start just before the line currently displayed at the top of the screen.
  959. X */
  960. X#ifdef __STDC__
  961. Xvoid backward (int n, int only_last)
  962. X#else
  963. X        public void
  964. Xbackward(n, only_last)
  965. X        int n;
  966. X        int only_last;
  967. X#endif
  968. X{
  969. X        POSITION pos;
  970. X
  971. X        pos = position(TOP);
  972. X        if (pos == NULL_POSITION)
  973. X        {
  974. X                /*
  975. X                 * This will almost never happen,
  976. X                 * because the top line is almost never empty.
  977. X                 */
  978. X                eof_bell();
  979. X                return;
  980. X        }
  981. X        back(n, pos, 0, only_last);
  982. X}
  983. X
  984. X/*
  985. X * Repaint the screen, starting from a specified position.
  986. X */
  987. X#ifdef __STDC__
  988. Xstatic void prepaint (POSITION pos)
  989. X#else
  990. X        static void
  991. Xprepaint(pos)
  992. X        POSITION pos;
  993. X#endif
  994. X{
  995. X        hit_eof = 0;
  996. X        forw(sc_height-1, pos, 1, 0);
  997. X}
  998. X
  999. X/*
  1000. X * Repaint the screen.
  1001. X */
  1002. X#ifdef __STDC__
  1003. Xvoid repaint (void)
  1004. X#else
  1005. X        public void
  1006. Xrepaint()
  1007. X#endif
  1008. X{
  1009. X        /*
  1010. X         * Start at the line currently at the top of the screen
  1011. X         * and redisplay the screen.
  1012. X         */
  1013. X#ifndef AMIGA
  1014. X        /* screen might have been resized */
  1015. X        POSITION savepos;
  1016. X
  1017. X        savepos = position(TOP);
  1018. X        pos_clear();
  1019. X        add_forw_pos(savepos);
  1020. X        prepaint(savepos);
  1021. X#else
  1022. X        prepaint(position(TOP));
  1023. X#endif
  1024. X}
  1025. X
  1026. X/*
  1027. X * Jump to the end of the file.
  1028. X * It is more convenient to paint the screen backward,
  1029. X * from the end of the file toward the beginning.
  1030. X */
  1031. X#ifdef __STDC__
  1032. Xvoid jump_forw (void)
  1033. X#else
  1034. X        public void
  1035. Xjump_forw()
  1036. X#endif
  1037. X{
  1038. X        POSITION pos;
  1039. X
  1040. X        if (ch_end_seek())
  1041. X        {
  1042. X                error("Cannot seek to end of file");
  1043. X                return;
  1044. X        }
  1045. X        lastmark();
  1046. X        pos = ch_tell();
  1047. X        clear();
  1048. X        pos_clear();
  1049. X        add_back_pos(pos);
  1050. X        back(sc_height - 1, pos, 0, 0);
  1051. X}
  1052. X
  1053. X/*
  1054. X * Jump to line n in the file.
  1055. X */
  1056. X#ifdef __STDC__
  1057. Xvoid jump_back (register int n)
  1058. X#else
  1059. X        public void
  1060. Xjump_back(n)
  1061. X        register int n;
  1062. X#endif
  1063. X{
  1064. X        register int c;
  1065. X        int nlines;
  1066. X
  1067. X        /*
  1068. X         * This is done the slow way, by starting at the beginning
  1069. X         * of the file and counting newlines.
  1070. X         */
  1071. X        if (ch_seek((POSITION)0))
  1072. X        {
  1073. X                /*
  1074. X                 * Probably a pipe with beginning of file no longer buffered.
  1075. X                 * If he wants to go to line 1, we do the best we can,
  1076. X                 * by going to the first line which is still buffered.
  1077. X                 */
  1078. X                if (n <= 1 && ch_beg_seek() == 0)
  1079. X                        jump_loc(ch_tell());
  1080. X                error("Cannot get to beginning of file");
  1081. X                return;
  1082. X        }
  1083. X
  1084. X        /*
  1085. X         * Start counting lines.
  1086. X         */
  1087. X        for (nlines = 1;  nlines < n;  nlines++)
  1088. X        {
  1089. X                while ((c = ch_forw_get()) != '\n')
  1090. X                        if (c == EOF)
  1091. X                        {
  1092. X                                char message[40];
  1093. X                                sprintf(message, "File has only %d lines",
  1094. X                                        nlines-1);
  1095. X                                error(message);
  1096. X                                return;
  1097. X                        }
  1098. X        }
  1099. X
  1100. X        jump_loc(ch_tell());
  1101. X}
  1102. X
  1103. X/*
  1104. X * Jump to a specified percentage into the file.
  1105. X * This is a poor compensation for not being able to
  1106. X * quickly jump to a specific line number.
  1107. X */
  1108. X#ifdef __STDC__
  1109. Xvoid jump_percent (int percent)
  1110. X#else
  1111. X        public void
  1112. Xjump_percent(percent)
  1113. X        int percent;
  1114. X#endif
  1115. X{
  1116. X        POSITION pos, len;
  1117. X        register int c;
  1118. X
  1119. X        /*
  1120. X         * Determine the position in the file
  1121. X         * (the specified percentage of the file's length).
  1122. X         */
  1123. X        if ((len = ch_length()) == NULL_POSITION)
  1124. X        {
  1125. X                error("Don't know length of file");
  1126. X                return;
  1127. X        }
  1128. X        pos = (percent * len) / 100;
  1129. X
  1130. X        /*
  1131. X         * Back up to the beginning of the line.
  1132. X         */
  1133. X        if (ch_seek(pos) == 0)
  1134. X        {
  1135. X                while ((c = ch_back_get()) != '\n' && c != EOF)
  1136. X                        ;
  1137. X                if (c == '\n')
  1138. X                        (void) ch_forw_get();
  1139. X                pos = ch_tell();
  1140. X        }
  1141. X        jump_loc(pos);
  1142. X}
  1143. X
  1144. X/*
  1145. X * Jump to a specified position in the file.
  1146. X */
  1147. X#ifdef __STDC__
  1148. Xvoid jump_loc (POSITION pos)
  1149. X#else
  1150. X        public void
  1151. Xjump_loc(pos)
  1152. X        POSITION pos;
  1153. X#endif
  1154. X{
  1155. X        register int nline;
  1156. X        POSITION tpos;
  1157. X
  1158. X        /*
  1159. X         * See if the desired line is BEFORE the currently
  1160. X         * displayed screen.  If so, see if it is close enough
  1161. X         * to scroll backwards to it.
  1162. X         * {{ This can be expensive if he has specified a very
  1163. X         *    large back_scroll count.  Perhaps we should put
  1164. X         *    some sanity limit on the loop count here. }}
  1165. X         */
  1166. X        tpos = position(TOP);
  1167. X        if (tpos != NULL_POSITION && pos < tpos)
  1168. X        {
  1169. X                int bs = get_back_scroll();
  1170. X                for (nline = 1;  nline <= bs;  nline++)
  1171. X                {
  1172. X                        tpos = back_line(tpos);
  1173. X                        if (tpos == NULL_POSITION)
  1174. X                                break;
  1175. X                        if (tpos <= pos)
  1176. X                        {
  1177. X                                back(nline, position(TOP), 1, 0);
  1178. X                                return;
  1179. X                        }
  1180. X                }
  1181. X        } else if ((nline = onscreen(pos)) >= 0)
  1182. X        {
  1183. X                /*
  1184. X                 * The line is currently displayed.
  1185. X                 * Just scroll there.
  1186. X                 */
  1187. X                forw(nline, position(BOTTOM_PLUS_ONE), 1, 0);
  1188. X                return;
  1189. X        }
  1190. X
  1191. X        /*
  1192. X         * Line is not on screen.
  1193. X         * Remember where we were; clear and paint the screen.
  1194. X         */
  1195. X        if (ch_seek(pos))
  1196. X        {
  1197. X                error("Cannot seek to that position");
  1198. X                return;
  1199. X        }
  1200. X        lastmark();
  1201. X        prepaint(pos);
  1202. X}
  1203. X
  1204. X/*
  1205. X * The table of marks.
  1206. X * A mark is simply a position in the file.
  1207. X */
  1208. X#define NMARKS          (27)            /* 26 for a-z plus one for quote */
  1209. X#define LASTMARK        (NMARKS-1)      /* For quote */
  1210. Xstatic POSITION marks[NMARKS];
  1211. X
  1212. X/*
  1213. X * Initialize the mark table to show no marks are set.
  1214. X */
  1215. X#ifdef __STDC__
  1216. Xvoid init_mark (void)
  1217. X#else
  1218. X        public void
  1219. Xinit_mark()
  1220. X#endif
  1221. X{
  1222. X        int i;
  1223. X
  1224. X        for (i = 0;  i < NMARKS;  i++)
  1225. X                marks[i] = NULL_POSITION;
  1226. X}
  1227. X
  1228. X/*
  1229. X * See if a mark letter is valid (between a and z).
  1230. X */
  1231. X#ifdef __STDC__
  1232. Xstatic int badmark (int c)
  1233. X#else
  1234. X        static int
  1235. Xbadmark(c)
  1236. X        int c;
  1237. X#endif
  1238. X{
  1239. X        if (c < 'a' || c > 'z')
  1240. X        {
  1241. X                error("Choose a letter between 'a' and 'z'");
  1242. X                return (1);
  1243. X        }
  1244. X        return (0);
  1245. X}
  1246. X
  1247. X/*
  1248. X * Set a mark.
  1249. X */
  1250. X#ifdef __STDC__
  1251. Xvoid setmark (int c)
  1252. X#else
  1253. X        public void
  1254. Xsetmark(c)
  1255. X        int c;
  1256. X#endif
  1257. X{
  1258. X        if (badmark(c))
  1259. X                return;
  1260. X        marks[c-'a'] = position(TOP);
  1261. X}
  1262. X
  1263. X#ifdef __STDC__
  1264. Xvoid lastmark (void)
  1265. X#else
  1266. X        public void
  1267. Xlastmark()
  1268. X#endif
  1269. X{
  1270. X        marks[LASTMARK] = position(TOP);
  1271. X}
  1272. X
  1273. X/*
  1274. X * Go to a previously set mark.
  1275. X */
  1276. X#ifdef __STDC__
  1277. Xvoid gomark (int c)
  1278. X#else
  1279. X        public void
  1280. Xgomark(c)
  1281. X        int c;
  1282. X#endif
  1283. X{
  1284. X        POSITION pos;
  1285. X
  1286. X        if (c == '\'')
  1287. X                pos = marks[LASTMARK];
  1288. X        else if (badmark(c))
  1289. X                return;
  1290. X        else
  1291. X                pos = marks[c-'a'];
  1292. X
  1293. X        if (pos == NULL_POSITION)
  1294. X                error("mark not set");
  1295. X        else
  1296. X                jump_loc(pos);
  1297. X}
  1298. X
  1299. X/*
  1300. X * Get the backwards scroll limit.
  1301. X * Must call this function instead of just using the value of
  1302. X * back_scroll, because the default case depends on sc_height and
  1303. X * top_scroll, as well as back_scroll.
  1304. X */
  1305. X#ifdef __STDC__
  1306. Xint get_back_scroll (void)
  1307. X#else
  1308. X        public int
  1309. Xget_back_scroll()
  1310. X#endif
  1311. X{
  1312. X        if (back_scroll >= 0)
  1313. X#ifdef AMIGA
  1314. X                return (back_scroll < sc_height? back_scroll: sc_height - 1);
  1315. X#else
  1316. X                return (back_scroll);
  1317. X#endif
  1318. X        if (top_scroll)
  1319. X                return (sc_height - 2);
  1320. X        return (sc_height - 1);
  1321. X}
  1322. X
  1323. X/*
  1324. X * Search for the n-th occurence of a specified pattern,
  1325. X * either forward (direction == '/'), or backwards (direction == '?').
  1326. X */
  1327. X#ifdef __STDC__
  1328. Xvoid search (int direction, char *pattern, register int n)
  1329. X#else
  1330. X        public void
  1331. Xsearch(direction, pattern, n)
  1332. X        int direction;
  1333. X        char *pattern;
  1334. X        register int n;
  1335. X#endif
  1336. X{
  1337. X        register int search_forward = (direction == '/');
  1338. X        POSITION pos, linepos;
  1339. X
  1340. X#if RECOMP
  1341. X        char *re_comp();
  1342. X        char *errmsg;
  1343. X
  1344. X        /*
  1345. X         * (re_comp handles a null pattern internally,
  1346. X         *  so there is no need to check for a null pattern here.)
  1347. X         */
  1348. X        if ((errmsg = re_comp(pattern)) != NULL)
  1349. X        {
  1350. X                error(errmsg);
  1351. X                return;
  1352. X        }
  1353. X#else
  1354. X#if REGCMP
  1355. X#ifdef AMIGA
  1356. X        static regexp *cpattern = NULL;
  1357. X#else
  1358. X        char *regcmp();
  1359. X        static char *cpattern = NULL;
  1360. X#endif
  1361. X
  1362. X        if (pattern == NULL || *pattern == '\0')
  1363. X        {
  1364. X                /*
  1365. X                 * A null pattern means use the previous pattern.
  1366. X                 * The compiled previous pattern is in cpattern, so just use it.
  1367. X                 */
  1368. X                if (cpattern == NULL)
  1369. X                {
  1370. X                        error("No previous regular expression");
  1371. X                        return;
  1372. X                }
  1373. X        } else
  1374. X        {
  1375. X                /*
  1376. X                 * Otherwise compile the given pattern.
  1377. X                 */
  1378. X#ifdef AMIGA
  1379. X                regexp *s;
  1380. X#else
  1381. X                char *s;
  1382. X#endif
  1383. X                if ((s = regcmp(pattern, 0)) == NULL)
  1384. X                {
  1385. X#ifdef AMIGA
  1386. X                        /* regexp had already displayed a more specific
  1387. X                           error message
  1388. X                         */
  1389. X#else
  1390. X                        error("Invalid pattern");
  1391. X#endif
  1392. X                        return;
  1393. X                }
  1394. X                if (cpattern != NULL)
  1395. X                        free((char *)cpattern);
  1396. X
  1397. X                cpattern = s;
  1398. X        }
  1399. X#else
  1400. X        static char lpbuf[100];
  1401. X        static char *last_pattern = NULL;
  1402. X
  1403. X        if (pattern == NULL || *pattern == '\0')
  1404. X        {
  1405. X                /*
  1406. X                 * Null pattern means use the previous pattern.
  1407. X                 */
  1408. X                if (last_pattern == NULL)
  1409. X                {
  1410. X                        error("No previous regular expression");
  1411. X                        return;
  1412. X                }
  1413. X                pattern = last_pattern;
  1414. X        } else
  1415. X        {
  1416. X                strcpy(lpbuf, pattern);
  1417. X                last_pattern = lpbuf;
  1418. X        }
  1419. X#endif
  1420. X#endif
  1421. X
  1422. X        /*
  1423. X         * Figure out where to start the search.
  1424. X         */
  1425. X
  1426. X        if (position(TOP) == NULL_POSITION)
  1427. X        {
  1428. X                /*
  1429. X                 * Nothing is currently displayed.
  1430. X                 * Start at the beginning of the file.
  1431. X                 * (This case is mainly for first_cmd searches,
  1432. X                 * for example, "+/xyz" on the command line.)
  1433. X                 */
  1434. X                pos = (POSITION)0;
  1435. X        } else if (!search_forward)
  1436. X        {
  1437. X                /*
  1438. X                 * Backward search: start just before the top line
  1439. X                 * displayed on the screen.
  1440. X                 */
  1441. X                pos = position(TOP);
  1442. X        } else if (top_search)
  1443. X        {
  1444. X                /*
  1445. X                 * Forward search and "start from top".
  1446. X                 * Start at the second line displayed on the screen.
  1447. X                 */
  1448. X                pos = position(TOP_PLUS_ONE);
  1449. X        } else
  1450. X        {
  1451. X                /*
  1452. X                 * Forward search but don't "start from top".
  1453. X                 * Start just after the bottom line displayed on the screen.
  1454. X                 */
  1455. X                pos = position(BOTTOM_PLUS_ONE);
  1456. X        }
  1457. X
  1458. X        if (pos == NULL_POSITION)
  1459. X        {
  1460. X                /*
  1461. X                 * Can't find anyplace to start searching from.
  1462. X                 */
  1463. X                error("Nothing to search");
  1464. X                return;
  1465. X        }
  1466. X
  1467. X        for (;;)
  1468. X        {
  1469. X                /*
  1470. X                 * Get lines until we find a matching one or
  1471. X                 * until we hit end-of-file (or beginning-of-file
  1472. X                 * if we're going backwards).
  1473. X                 */
  1474. X#ifdef AMIGA
  1475. X                if (chk_sigs())
  1476. X#else
  1477. X                if (sigs)
  1478. X#endif
  1479. X                        /*
  1480. X                         * A signal aborts the search.
  1481. X                         */
  1482. X                        return;
  1483. X
  1484. X                if (search_forward)
  1485. X                {
  1486. X                        /*
  1487. X                         * Read the next line, and save the
  1488. X                         * starting position of that line in linepos.
  1489. X                         */
  1490. X                        linepos = pos;
  1491. X                        pos = forw_raw_line(pos);
  1492. X                } else
  1493. X                {
  1494. X                        /*
  1495. X                         * Read the previous line and save the
  1496. X                         * starting position of that line in linepos.
  1497. X                         */
  1498. X                        pos = back_raw_line(pos);
  1499. X                        linepos = pos;
  1500. X                }
  1501. X
  1502. X                if (pos == NULL_POSITION)
  1503. X                {
  1504. X                        /*
  1505. X                         * We hit EOF/BOF without a match.
  1506. X                         */
  1507. X                        error("Pattern not found");
  1508. X                        return;
  1509. X                }
  1510. X
  1511. X                /*
  1512. X                 * Test the next line to see if we have a match.
  1513. X                 * This is done in a variety of ways, depending
  1514. X                 * on what pattern matching functions are available.
  1515. X                 */
  1516. X#if REGCMP
  1517. X                if ( (regex(cpattern, line) != NULL)
  1518. X#else
  1519. X#if RECOMP
  1520. X                if ( (re_exec(line) == 1)
  1521. X#else
  1522. X                if ( (match(pattern, line))
  1523. X#endif
  1524. X#endif
  1525. X                                && (--n <= 0) )
  1526. X                        /*
  1527. X                         * Found the matching line.
  1528. X                         */
  1529. X                        break;
  1530. X        }
  1531. X
  1532. X        jump_loc(linepos);
  1533. X}
  1534. X
  1535. X
  1536. X#if (!REGCMP) && (!RECOMP)
  1537. X/*
  1538. X * We have neither regcmp() nor re_comp().
  1539. X * We use this function to do simple pattern matching.
  1540. X * It supports no metacharacters like *, etc.
  1541. X */
  1542. X        static int
  1543. Xmatch(pattern, buf)
  1544. X        char *pattern, *buf;
  1545. X{
  1546. X        register char *pp, *lp;
  1547. X
  1548. X        for ( ;  *buf != '\0';  buf++)
  1549. X        {
  1550. X                for (pp = pattern, lp = buf;  *pp == *lp;  pp++, lp++)
  1551. X                        if (*pp == '\0' || *lp == '\0')
  1552. X                                break;
  1553. X                if (*pp == '\0')
  1554. X                        return (1);
  1555. X        }
  1556. X        return (0);
  1557. X}
  1558. X#endif
  1559. X
  1560. END_OF_FILE
  1561. if test 22479 -ne `wc -c <'Less1.4Z/src/prim.c'`; then
  1562.     echo shar: \"'Less1.4Z/src/prim.c'\" unpacked with wrong size!
  1563. fi
  1564. # end of 'Less1.4Z/src/prim.c'
  1565. fi
  1566. echo shar: End of archive 4 \(of 7\).
  1567. cp /dev/null ark4isdone
  1568. MISSING=""
  1569. for I in 1 2 3 4 5 6 7 ; do
  1570.     if test ! -f ark${I}isdone ; then
  1571.     MISSING="${MISSING} ${I}"
  1572.     fi
  1573. done
  1574. if test "${MISSING}" = "" ; then
  1575.     echo You have unpacked all 7 archives.
  1576.     rm -f ark[1-9]isdone
  1577. else
  1578.     echo You still need to unpack the following archives:
  1579.     echo "        " ${MISSING}
  1580. fi
  1581. ##  End of shell archive.
  1582. exit 0
  1583. -- 
  1584. Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
  1585. Mail comments to the moderator at <amiga-request@uunet.uu.net>.
  1586. Post requests for sources, and general discussion to comp.sys.amiga.misc.
  1587.